1人でもWebアプリ(Laravel + React)を速く開発しつづける環境をつくる
本記事でわからないことがあれば↑にコメントを下さい。できる限りお答えします。
個人開発は面白いので気軽にチャレンジしたいですよね。一方で、開発環境やデプロイフローを作るのは最初知識がないと後回しにしがちです。しかし、CI/CDは最初に組んだほうがいいし、IDEの設定も最初にすると積分で効いてきます。手軽な開発・運用環境を構築するのがこの記事の役割です。
https://gyazo.com/af7b9830db10fb43e05c0871b33fba2b
最終的な構成は上図のようになります
右側では、Heroku上にアプリケーションのがホストされています
WebサーバとしてApacheを利用しますが、Herokuが自動的に設定してくれるので、開発者はほぼ意識しないため、書いていません
細かいことは現時点でわからなくても大丈夫です
このチュートリアルでできるのはこのようなサイトです。DBからデータを取得して文字列を表示しています。 サイトの内容自体に意味はありません。これを実現する設定の紹介が本記事の役割です。
リポジトリをcloneして試すことができます
CircleCIやHerokuといった有償のサービスを利用しますが、無料の範囲で試すことができます。ぜひ手を動かしてみてください。
TL;DR
LaravelとReactでWebアプリケーションを個人開発するための流れを紹介します
具体的には次のような項目を説明しています
フロント/バックエンドの開発環境の作成方法
バックエンド開発にPHPのWeb Application FrameworkであるLaravel テストフレームワークはPHPUnit(Laravelデフォルト)
フロントエンド開発にReact + TypeScript IDE(IntelliJ IDEA(有償版))の設定方法
GraphQLによるAPI作成
LaravelのフロントエンドをReactにするつなぎこみ
この記事の特徴は、Herokuデプロイを前提としたこのつなぎこみの解説
Herokuでの継続的デプロイメント
PHPとTypeScriptの混在するリポジトリでのHerokuの設定方法
HerokuのGitHub連携により、masterブランチにマージされたコードを自動的にデプロイ コミットに対する自動テストと静的解析
CircleCIを使い、GitHubにcommitをプッシュするごとにCIを回す
PHPUnitのテストを回す
CIが落ちたらマージできなくする
ロギング
サーバにエラーがあったら通知してほしいし原因を探りたい
この記事の想定読者
PHP + LaravelでWebアプリケーションを作りたい、かつフロントはLaravelのテンプレートエンジンBladeではなく、ReactやVueなどに差し替えたい方 LaravelやReact自体の機能説明はしません
個人開発において、最低限の開発環境が欲しい方
次のことはできると仮定します
基本的なLinuxのコマンドがわかる
GitHubが使える
説明を適宜省略しますが、Scrapboxは単語から連携して関連記事が出て、それをたどることで目当ての情報にたどり着けるかもしれません
例えば上の「Laravel」をクリックするとLaravel自体の説明を書いています。Herokuの説明はしませんが、Herokuに軽く説明が書いてあります 個人でアプリケーションを作成していることがある方はやっていることだと思うので、得るものはあまりないと思います
まえがき:個人開発は楽しい
Webアプリケーションは個人でも「結構便利」レベルの問題解決ができるのが魅力です
一方、人間の学習能力はそう簡単にあがりません。困りましたね。ただ、学習環境や、PaaSなどの楽をするしくみが整い始めました 学習環境の例
GitHubによって高品質なソースコードや開発の過程を見ることができるようになった
2019年現在、個人開発でWebアプリを作るときの構成としては、クライアントをVue/React/Angular(ネイティブアプリとWeb両方対応したいならFlutter)などでかき、バックエンドはFirebaseやAWSの各種サービスを使うことも多いと思います。
Firebase便利!Firebaseを使おう!
〜完〜
……そのような構成は他の誰かが書いてくれるはずなので、本記事ではバックエンドとしてHerokuを採用します。
Herokuを使うと嬉しいことは次のとおりです。
LaravelのようなWAFを動かすことができる
「Laravelを学習しながら、Webアプリケーションをつくってみたい。ついでに最近のフロントエンドを学んでみるか〜」というときに便利
設定が楽で、月額0円〜1000円程度で比較的安価かつ定額でアプリをホストできる
本当に格安を求めるとVPSとかになると思いますが、デプロイフローの簡略化と価格のバランスが取れていると思います
この記事で得られる開発環境
以降では、冒頭で述べたような「そこそこ満足できる開発環境」の構成をつくっていきます。
日々の開発の流れは次のようになります。
開発者は、コードを書いてローカル環境で確認する
GitHubにcommitをPushしてPRをつくる
コードが静的解析され、まずいところがコメントされる
PRに問題なければマージをする
自動的にプロダクション環境(実際にユーザーがサービスをさわれる環境のこと)に反映される
開発環境をつくる
https://gyazo.com/6b08c39df14eb31308151e6833faa54a
フロントエンドとバックエンドのローカル環境をつくります。それぞれ、公式に提供されているものを利用する設定をしていきます。
再現環境
vagrant 2.2.6
yarn 1.19.2
node v13.2.0
下の手順をやっていて、なんかおかしいなと思ったらバージョンを確認してみてください
バックエンドの開発環境をつくる
Laravelは公式にVagrantで動くVMイメージであるHomesteadが提供されているので設定します ミドルウェアも全部入りなので、この上で開発することができます
以下では、デフォルトの設定であると仮定します。すなわち次のような設定であるとします。
code:Homestead.yaml
folders:
# localのディレクトリはここにあると仮定します
- map: ~/dev/laravel-cra-template
# vagrant上のcode/にmappingされる
to: /home/vagrant/code
sites:
# laravel-react.testにアクセスすると
- map: laravel-react.test
# code/publicへのアクセスになる(laravelデフォルトの設定だとindex.phpがよばれる)
to: /home/vagrant/code/public
Laravelプロジェクトを作成する
Laravelのインストール
code:zsh
# homestead.yamlのあるディレクトリで
vagrant ssh
# homestead上で
cd code
composer create-project --prefer-dist laravel/laravel .
https://gyazo.com/0de67267d2110ed63e008ef35acaad48
次はフロントエンドの開発環境をつくっていきます。
フロントエンドの開発環境をつくる
Reactコミュニティが公式提供しているテンプレートで、以下の理由で初学者におすすめです
ベストプラクティスがつまった開発環境が提供されている
WebpackやBabelといった初学者には複雑なレイヤーが隠蔽されている(設定に悩むのではなくて、アプリケーションを書きたいですよね?)。かつ、いざとなれば自分でWebpackの設定を書くことができる
デフォルトはJavaScriptで書くことになりますが、TypeScriptで書くためのテンプレートが用意されています。今回はこちらを使います。型があるとコード補完でサボれて便利。
インストール
code:zsh
# 手元PC上で
cd ~/dev/laravel-cra-template
# project root直下のfrontディレクトリにReactのプロジェクトを作成します
yarn create react-app front --typescript
起動
code:zsh
cd front
# 起動
yarn run start
https://gyazo.com/56b2edeae5bd28cd4e67f700e1c8a93b
ここまででフロントエンドの開発環境が整いました。
次にこれをデプロイしていきます。しかし、そのまえにやることがあります。
LaravelへのリクエストをReactでハンドリングする
ここまでの設定は、以下のような開発環境を想定した設定です
localhost(Ceate React App) - APIアクセス -> Laravel(homestead)
HTTPサーバーがlocalhostとhomestead(Apache)の2つたっていることがわかります
ところで、このアプリケーションはHerokuにホストします。
開発環境と同じ構成でフロントのためにサーバを建てるとその分インスタンスが必要で運用コストが上がってしまいます。そこで、1インスタンス(Heroku用語ではDyno)に乗せることを考えます。
これを実現するために、次のような設定をしていきましょう
デプロイの際にReactをビルドして、public/以下にビルド結果を配置する
Laravelへのリクエスト(GET /など)を、Reactにわたす設定を書く
https://gyazo.com/837a8f40f2c214858c82a02dc7deeb98
実現したいこと
アイデア
Homesteadのデフォルトのルーティングでは、public/以下にアクセスするようになっているので、フロントのビルド結果をここにおきます
手順
front/package.jsonに次のコマンドを追加します
"build:production": "yarn build && mv build/* ../public",
次のルーティングをroutes/web.phpに追加します
code:web.php
<?php
# どのルートにもマッチしないときに
Route::fallback(function () {
# public/index.htmlにはCRAのビルド結果がおいてある
return file_get_contents(public_path('index.html'));
});
この設定をしておくと、APIを作成したときにLaravel側にルーティングが存在すればそれが利用されるようになります。この設定はとても重要です。すべてのリクエストはLaravelがまずうけ、そののちにルーティングしていることを意識してください。
本番ではこのビルドが必要になるので、Herokuにデプロイする際に自動化します
開発環境のフロント開発においては、yarn run startをつかってローカルサーバをたてて開発をするので、このコマンドは開発環境でつかうことはありません。
Herokuにデプロイする
https://gyazo.com/2238fc29a92b440c1245d1857f017010
ここまでで、フロントエンドの成果物をブラウザで表示できるようになりました。
一旦Herokuにデプロイしましょう。Herokuを使うのは手軽だからです。 手順
例として、kadoyau-laravel-reactという名前にしました。以下ではこれをYOUR_APP_NAMEとよびます。
GitHubからデプロイできるようにします
GitHubを紐付けます
https://gyazo.com/e162e9f49c9ebf1824b3658dcf46bb7c
masterブランチをpushする(あるいはPull Requestがmasterにマージされる)ごとにデプロイする設定にします
https://gyazo.com/1a696b9f68676786473d3878af5f5380
Laravelに必要な環境変数を設定する
.envの内容を設定しましょう。HerokuではPostgreSQLが標準で、HomesteadはデフォルトMySQLなので接続先をPostgreSQLにかえる設定も混ぜておきます。
code:.envの内容をコマンドにしたもの
heroku config:set -a YOUR_APP_NAME \
APP_KEY=base64:YOUR_KEY_IS_HERE \
APP_NAME=laravel-react\
APP_ENV=production \
APP_DEBUG=false \
LOG_CHANNEL=stack
pushするだけではrootディレクトリのcomposer.lock(PHP)しか認識されてインストールされません
クライアントのプロジェクトもビルドしたいので、ビルドパックを追加します
一度でもデプロイをしていれば、heroku/phpは自動的に検知されていると思います
https://gyazo.com/f2eb7bbfc8d18d1f1862b631bff71e1c
ロギングの設定をする
papertrailというログ保存サービスがあるのでそのアドオンを使うとよいです
デプロイが完了すると以下のように表示されます
https://gyazo.com/48d661e27a782aba6e8e8e479abe8ea7
🚀ここまででできるようになったこと
フロントとバックエンドの開発環境が揃った
masterブランチにコミットしたものが自動的にHerokuにデプロイされるようになった
エラーやアクセスログをpapertrailのダッシュボードで見ることができるようになった
次はこんなことがしたくなると思います
Laravelでアプリケーションを作成してAPIを公開する
ReactのフロントでそのAPIを叩く
やっていきましょう💪
APIを作成し、開発環境で動くようにする
この例ではMySQLのuserテーブルに格納されているユーザの名前を返すAPIを作りました
DBのシーディングもしておきます
フロントからHomestead上のGraphQL APIを利用する準備をする
GraphQLのクライアントライブラリApolloを入れます code:zsh
yarn add apollo-boost graphql react-apollo
userを取得して表示します
コードを書いてlocalhost:3000(CRAが起動しているポート)にアクセスすると、エラーになります https://gyazo.com/6d2c739285a2f5524b5dca6906669751
Chrome dev toolを見てみると、404になっています
https://gyazo.com/a0a8aad83166db6f7ee6d93cdcd56234
localhostには/graphqlというエンドポイントはないので、CRA側でハンドリングされて404になっています
React側にコードがない際にリクエストをLaravel側にproxyする設定を入れます
code:client/package.json
一度ローカルサーバを落としてからyarn run start正常に表示されるようになりました
https://gyazo.com/b2e38103dea4e3ecd9dd6875ab5a7037
APIを本番環境で利用可能にする(HerokuでDBを作成し、接続設定をし、Seedingする)
作成したAPIをHerokuにデプロイしてみます。デプロイ自体は前述のとおりmasterブランチにコミットするだけです。
しかし、この状態でデプロイすると以下のようにエラーが表示されてしまいます。
https://gyazo.com/38bcd055e3adbce86a9550837d32ba1e
HerokuのDBに接続できないのが原因です。LaravelからDBに接続するための設定をしていきます。
HerokuのDBを設定を接続する
HerokuはMySQLではなくPostgres。Addonを追加する
https://gyazo.com/acfa86d6cd28af958c4ebf5e94ed40ca
Heroku Postgresをクリックして、データベースのcredentialを確認する
https://gyazo.com/f2a59400ac26b9c91086763f75b423c7
ここにユーザー名やパスワードが記載されている
LaravelからDBに接続するために環境変数を追加する
code:zsh
heroku config:set -a YOUR_APP_NAME \
DB_CONNECTION=pgsql \
DB_HOST=上で確認したもの \
DB_PORT=上で確認したもの \
DB_DATABASE=上で確認したもの \
DB_USERNAME=上で確認したもの \
DB_PASSWORD=上で確認したもの
Heroku上でDBをマイグレーションする
code:zsh
$ heroku run bash -a kadoyau-laravel-react
Running bash on ⬢ kadoyau-laravel-react... up, run.1796 (Free)
~ $ php artisan migrate
**************************************
* Application In Production! *
**************************************
Do you really wish to run this command? (yes/no) no: yes
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table (0.03 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table (0.04 seconds)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated: 2019_08_19_000000_create_failed_jobs_table (0.02 seconds)
Seedingする
code:zsh
$ php artisan db:seed --class=UsersTableSeeder
**************************************
* Application In Production! *
**************************************
Do you really wish to run this command? (yes/no) no: yes
Database seeding completed successfully.
これで本番でもAPIの結果が表示されるようになりました。
CI環境を作ろう
https://gyazo.com/73424063fa9d0261eb7b7d3d2fb5a023
ここをつくっていきます
CIではいろいろなことができますが、テストと静的解析をかけます
テストを追加する
CI環境で回すためにテスト
Laravelのデフォルトがすでにあるのでそれをつかいます
CircleCIの設定をする
CircleCIにログインして、プロジェクトをセットアップします(リポジトリを選ぶだけ)
https://gyazo.com/9f487c5402b332e20d030eb43907423d
CircleCIの設定のためにconfig.ymlを書いてGitHubにpushします
テストが通っていることが確認できます
https://gyazo.com/a6eb770556333c60711f9c821fad9616
静的解析をかけ、自動でレビューをしてもらおう
GitHubで、CIが落ちたらPRをマージできないようにします
https://gyazo.com/a60cd8fcf051916e3543fba8d56e4832
以上で、当初の目的を達成できました。お疲れさまでした。
さらに開発していくためのTips
Reactの別のページを追加する方法
「Laravel側で常にindex.htmlしか返さないんだったら、それ以外のページを作るにはどうすれば?たとえば/aboutページとかどう作るの?」とはじめてやったときに疑問に思いました
GET /でもGET /aboutでもLaravelはindex.htmlを返すのですが、React Routerが適切にルーティングをしてくれます。
Vueにもこのようなライブラリが存在します
アプリケーションとしてユーザに公開する際に便利な設定も紹介しておきます
Herokuではドメインが割り当てられますが、わかりやすいドメインをとるのもいいかもしれません(必須ではありません)
静的なリソースをユーザに送るときには、CDNを使うと早く、かつサーバの負荷も軽減できます。さらにCDNの各種サービスのメリットを受けることができます
ローカル環境のLaravelのデバッグ
IDEとしてIntelliJ IDEAを使うと、次のような便利なことがあります
Homestead環境のDBにアクセスしたり
手元からhomestead環境でUnit testを回すことができるようになったり
保存時にコードフォーマットを整える
静的解析をかける
設定しておきましょう
監視
関連